package com.liaowei.comment.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.liaowei.comment.mapper.ArticleCommentMapper;
import com.liaowei.comment.model.param.ArticleCommentParam;
import com.liaowei.comment.openfeign.ArticleClient;
import com.liaowei.comment.openfeign.UserClient;
import com.liaowei.comment.service.ArticleCommentService;
import com.liaowei.common.BaseResponse;
import com.liaowei.common.Constants;
import com.liaowei.common.ErrorCode;
import com.liaowei.exception.CustomerException;
import com.liaowei.model.domain.ArticleComment;
import com.liaowei.model.param.ArticleCommentStatusParam;
import com.liaowei.model.param.ArticleUserParam;
import com.liaowei.model.param.QueryManageArticleCommentParam;
import com.liaowei.model.vo.ArticleCommentVO;
import com.liaowei.model.vo.UserVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @author LindaMan
 * @description 针对表【wy_article_comment(文章-评论表)】的数据库操作Service实现
 * @createDate 2023-05-09 15:26:25
 */
@Service
@RequiredArgsConstructor
public class ArticleCommentServiceImpl extends ServiceImpl<ArticleCommentMapper, ArticleComment>
        implements ArticleCommentService {

    private final ArticleCommentMapper articleCommentMapper;
    private final ArticleClient articleClient;
    private final UserClient userClient;

    // 校验用户是否认证
    public void matchUser(Long userId, Long loginId) {
        if (!loginId.equals(userId)) {
            throw new CustomerException(Constants.PARAM_ERROR, "请先认证");
        }
    }

    // 根据id获取用户头像
    public String getAvatarByUserId(Long userId) {
        BaseResponse<UserVO> res = userClient.getById(userId);
        if (res.getCode() == 1) {
            return res.getData().getAvatar();
        }
        return "小鲲";
    }

    // 根据id获取用户别名
    public String getNicknameByUserId(Long userId) {
        BaseResponse<UserVO> res = userClient.getById(userId);
        if (res.getCode() == 1) {
            return res.getData().getNickname();
        }
        return "小鲲";
    }

    // 将articleComment转换为articleCommentVO
    public ArticleCommentVO toArticleCommentVO(ArticleComment comment) {
        ArticleCommentVO vo = new ArticleCommentVO();
        Long replyId = comment.getReplyId(); // 获取replyId
        // 对象复制
        BeanUtil.copyProperties(comment, vo);
        // 封装其他属性
        // nickname
        vo.setNickname(getNicknameByUserId(comment.getUserId()));

        // avatar
        vo.setAvatar(getAvatarByUserId(comment.getUserId()));

        // replyName
        // 判断回复类型
        Integer replyType = comment.getReplyType();
        if (replyType == Constants.COMMENT_REPLY_TYPE_CONTENT) {
            // 回复内容
            vo.setReplyName("");
        } else {
            // 回复用户
            vo.setReplyName(getNicknameByUserId(replyId));
        }

        // 返回结果
        return vo;
    }


    /**
     * 查询用户是否对该文章评论过
     * @param articleId 文章id
     * @param userId 用户id
     * @return 评论状态
     */
    @Override
    public List<ArticleComment> searchIsCommented(Long articleId, Long userId) {
        return Optional.ofNullable(articleCommentMapper.selectIsCommented(articleId,userId))
                .orElse(new ArrayList<>());
    }

    /**
     * 根据文章id删除文章的评论
     * @param articleId 文章id
     * @param userId 用户id
     * @return 提示信息
     */
    @Transactional
    @Override
    public String deleteArticleCommentByIdAndUserId(Long articleId, Long userId) {
        // 获取当前认证的id
        Long loginId = Long.parseLong(StpUtil.getLoginId().toString());

        // 判断是否是管理员继续操作
        if (userId != 1){ // 不是管理员
            // 判断当前要删除的是不是自己的评论
            matchUser(userId, loginId);
        }

        // 删除文章评论
        LambdaQueryWrapper<ArticleComment> wrapper = Wrappers.lambdaQuery(ArticleComment.class)
                .eq(ArticleComment::getArticleId, articleId);
        try {
            articleCommentMapper.delete(wrapper);
        }catch (Exception e){
            throw new CustomerException(ErrorCode.SYSTEM_ERROR);
        }

        return "删除成功";
    }

    /**
     * 后台-分页查询评论列表
     * @return IPage<ArticleComment>
     */
    @Override
    public IPage<ArticleCommentVO> searchManagePage(int pageNum, int pageSize) {
        // 构造分页构造器
        IPage<ArticleComment> page = new Page<>(pageNum,pageSize);

        // 分页查询
        articleCommentMapper.selectPage(page,
                Wrappers.lambdaUpdate(ArticleComment.class).orderByDesc(ArticleComment::getCreateTime));

        // 返封装voPage
        IPage<ArticleCommentVO> voPage = new Page<>(pageNum,pageSize);
        // 对象复制
        BeanUtil.copyProperties(page,voPage,"records");
        // 封装records
        List<ArticleCommentVO> voList = page.getRecords().stream()
                .map(this::toArticleCommentVO).collect(Collectors.toList());
        voPage.setRecords(voList);

        return voPage;
    }

    /**
     * 分页查询评论列表
     *
     * @param commentParam 分页条件参数
     * @return ArticleCommentVO分页数据
     */
    @Override
    public IPage<ArticleCommentVO> searchPage(QueryManageArticleCommentParam commentParam) {
        // 构造分页构造器
        IPage<ArticleComment> page = new Page<>(commentParam.getPageParam().getPageNum(),
                commentParam.getPageParam().getPageSize());

        // 构造查询构造器
        LambdaUpdateWrapper<ArticleComment> pageWrapper = Wrappers.lambdaUpdate(ArticleComment.class)
                .eq(ArticleComment::getArticleId, commentParam.getArticleId())
                .orderByDesc(ArticleComment::getCreateTime);

        // 分页查询
        articleCommentMapper.selectPage(page, pageWrapper);

        // 封装voPage
        IPage<ArticleCommentVO> voPage = new Page<>();
        // 对象复制
        BeanUtil.copyProperties(page, voPage, "records");
        // records封装
        List<ArticleCommentVO> voList = page.getRecords().stream()
                .map(this::toArticleCommentVO).collect(Collectors.toList());
        voPage.setRecords(voList);

        return voPage;
    }

    /**
     * 删除评论
     *
     * @param commentId 评论id
     * @return 提示信息
     */
    @Override
    public String deleteArticleComment(Long commentId, Long articleId, Long userId) {
        // 获取当前认证的id
        Long loginId = Long.parseLong(StpUtil.getLoginId().toString());

        // 判断是否是管理员继续操作
        if (userId != 1){ // 不是管理员
            // 判断当前要删除的是不是自己的评论
            matchUser(userId, loginId);
        }

        // 修改articleUser
        ArticleCommentStatusParam param = new ArticleCommentStatusParam();
        param.setArticleId(articleId);
        param.setUserId(userId);
        param.setCommentStatus(0);
        articleClient.commentStatus(param);

        // 删除评论
        articleCommentMapper.deleteById(commentId);

        return "删除成功";
    }

    /**
     * 评论文章
     *
     * @param commentParam 文章评论参数
     * @return 提示信息
     */
    @Transactional
    @Override
    public String saveArticleComment(ArticleCommentParam commentParam) {
        // 获取当前认证的id
        Long loginId = Long.parseLong(StpUtil.getLoginId().toString());
        // 获取回复id
        Long replyId = commentParam.getReplyId();
        // 获取文章id
        Long articleId = commentParam.getArticleId();

        // 对评论人id进行二次校验
        Long userId = commentParam.getUserId(); // 评论人id
        matchUser(userId, loginId);

        // 对回复类型进行判断
        Integer replyType = commentParam.getReplyType();
        if (replyType == Constants.COMMENT_REPLY_TYPE_CONTENT) {
            // 回复内容
            if (!Objects.equals(replyId, articleId))
                throw new CustomerException(Constants.PARAM_ERROR, "请回复合法对象");
        } else if (replyType == Constants.COMMENT_REPLY_TYPE_USER) {
            // 回复用户
            // 再查询是否已经有用户评论过
            LambdaQueryWrapper<ArticleComment> replyWrapper = Wrappers.lambdaQuery(ArticleComment.class)
                    .eq(ArticleComment::getUserId, replyId)
                    .eq(ArticleComment::getArticleId, articleId);
            Long count = articleCommentMapper.selectCount(replyWrapper);
            if (count < 1)
                throw new CustomerException(Constants.PARAM_ERROR, "请回复合法对象");
        } else {
            throw new CustomerException(Constants.PARAM_ERROR, "请回复合法对象");
        }

        // 添加文章评论
        ArticleComment articleComment = new ArticleComment();
        articleComment.setArticleId(articleId);
        articleComment.setContent(commentParam.getContent());
        articleComment.setUserId(userId);
        articleComment.setReplyId(replyId);
        articleComment.setReplyType(commentParam.getReplyType());
       articleComment.setParentId(commentParam.getParentId());
        try {
            // 保存articleUser 评论状态
            ArticleUserParam articleUserParam = new ArticleUserParam();
            articleUserParam.setArticleId(articleId);
            articleUserParam.setUserId(userId);
            articleUserParam.setCommentStatus(1);
            articleClient.saveArticleUser(articleUserParam);

            // 保存评论
            articleCommentMapper.insert(articleComment);
        } catch (Exception e) {
            throw new CustomerException(ErrorCode.SYSTEM_ERROR);
        }

        return "评论成功";
    }
}




